#!/bin/bash

# ===============================================
# Redis Stack 功能测试脚本
# 文件名: redis-stack-test.sh
# 版本: v1.1
# 创建时间: $(date +%Y-%m-%d)
# 功能: 测试Redis Stack的各项功能模块
# ===============================================

# 脚本配置参数
REDIS_HOST="localhost"
REDIS_PORT="6379"
REDIS_PASSWORD="Hlj@20220715"
TEST_TIMEOUT=30

# 日志配置
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOG_DIR="${SCRIPT_DIR}/logs"
LOG_FILE="${LOG_DIR}/redis-stack-test-$(date +%Y%m%d-%H%M%S).log"

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 初始化日志系统
init_log_system() {
    # 创建logs目录
    if [ ! -d "$LOG_DIR" ]; then
        mkdir -p "$LOG_DIR"
        if [ $? -ne 0 ]; then
            echo "错误: 无法创建日志目录 $LOG_DIR"
            exit 1
        fi
    fi
    
    # 创建日志文件
    touch "$LOG_FILE"
    if [ $? -ne 0 ]; then
        echo "错误: 无法创建日志文件 $LOG_FILE"
        exit 1
    fi
    
    # 记录脚本开始信息
    echo "===============================================" >> "$LOG_FILE"
    echo "Redis Stack 功能测试脚本 v1.1" >> "$LOG_FILE"
    echo "测试开始时间: $(date)" >> "$LOG_FILE"
    echo "日志文件: $LOG_FILE" >> "$LOG_FILE"
    echo "Redis服务: $REDIS_HOST:$REDIS_PORT" >> "$LOG_FILE"
    echo "===============================================" >> "$LOG_FILE"
    echo "" >> "$LOG_FILE"
}

# 文件日志记录函数
log_to_file() {
    local level="$1"
    local message="$2"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$level] $timestamp - $message" >> "$LOG_FILE"
}

# 控制台和文件日志函数
log_info() {
    echo -e "${BLUE}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
    log_to_file "INFO" "$1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
    log_to_file "SUCCESS" "$1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
    log_to_file "WARN" "$1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
    log_to_file "ERROR" "$1"
}

# 安装Redis客户端
install_redis_cli() {
    log_info "检测到redis-cli未安装，尝试自动安装..."
    
    # 检测系统类型
    if command -v yum &> /dev/null; then
        # CentOS/RHEL/Alibaba Cloud Linux
        log_info "检测到yum包管理器，安装Redis客户端..."
        yum install -y redis 2>/dev/null
        if [ $? -eq 0 ]; then
            log_success "Redis客户端安装成功"
            return 0
        fi
    elif command -v apt-get &> /dev/null; then
        # Ubuntu/Debian
        log_info "检测到apt包管理器，安装Redis客户端..."
        apt-get update && apt-get install -y redis-tools 2>/dev/null
        if [ $? -eq 0 ]; then
            log_success "Redis客户端安装成功"
            return 0
        fi
    fi
    
    log_error "自动安装失败，请手动安装Redis客户端"
    log_info "CentOS/RHEL/Alibaba Cloud Linux: sudo yum install -y redis"
    log_info "Ubuntu/Debian: sudo apt-get update && sudo apt-get install -y redis-tools"
    return 1
}

# 检查Redis连接
check_redis_connection() {
    log_info "检查Redis连接..."
    
    if ! command -v redis-cli &> /dev/null; then
        log_warn "redis-cli未安装"
        
        # 尝试自动安装，如果失败则提示手动安装
        log_info "尝试自动安装Redis客户端..."
        install_redis_cli
        
        if [ $? -ne 0 ]; then
            log_error "自动安装失败，请手动安装Redis客户端"
            log_info "安装命令:"
            log_info "CentOS/RHEL/Alibaba Cloud Linux: sudo yum install -y redis"
            log_info "Ubuntu/Debian: sudo apt-get update && sudo apt-get install -y redis-tools"
            log_info "安装完成后重新运行测试脚本"
            return 1
        fi
    fi
    
    # 测试连接
    if redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" ping 2>/dev/null | grep -q "PONG"; then
        log_success "Redis连接正常"
        return 0
    else
        log_error "无法连接到Redis服务"
        log_info "请检查:"
        log_info "1. Redis服务是否运行: systemctl status docker"
        log_info "2. 容器状态: docker ps | grep redis-stack"
        log_info "3. 防火墙设置"
        log_info "4. Redis服务是否启动: docker exec redis-stack redis-cli ping"
        return 1
    fi
}

# 检查Redis Stack模块
check_redis_modules() {
    log_info "检查Redis Stack模块..."
    
    local module_info
    module_info=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" module list 2>/dev/null)
    
    if [ $? -ne 0 ]; then
        log_error "无法获取模块列表"
        return 1
    fi
    
    echo "已加载模块:"
    echo "$module_info"
    
    # 检查关键模块（Redis Stack 7.2+版本中graph模块已移除）
    local required_modules=("ReJSON" "search" "timeseries" "bf")
    local optional_modules=("graph")  # graph模块在Redis Stack 7.2+中为可选
    local missing_modules=()
    
    # 检查必需模块
    for module in "${required_modules[@]}"; do
        if echo "$module_info" | grep -qi "$module"; then
            log_success "✅ $module 模块已加载"
        else
            log_warn "⚠️ $module 模块未找到"
            missing_modules+=("$module")
        fi
    done
    
    # 检查可选模块
    for module in "${optional_modules[@]}"; do
        if echo "$module_info" | grep -qi "$module"; then
            log_success "✅ $module 模块已加载（可选）"
        else
            log_info "ℹ️ $module 模块未找到（在Redis Stack 7.2+版本中为可选模块）"
        fi
    done
    
    if [ ${#missing_modules[@]} -eq 0 ]; then
        log_success "所有必需Redis Stack模块加载成功"
        return 0
    else
        log_warn "部分必需模块缺失: ${missing_modules[*]}"
        return 1
    fi
}

# 测试RedisJSON功能
test_redisjson() {
    log_info "测试RedisJSON功能..."
    
    # 检查JSON模块是否可用
    if ! redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
JSON.SET test:json . '{"test":"json_module_check"}'
EOF
    then
        log_warn "RedisJSON模块可能未正确加载或权限不足"
        
        # 诊断信息：检查具体错误
        log_info "诊断信息：尝试直接执行JSON.SET命令..."
        local diagnostic_result
        diagnostic_result=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>&1
JSON.SET test_diagnostic . '{"test":"diagnostic"}'
EOF
)
        log_info "诊断结果: $diagnostic_result"
        
        return 1
    fi
    
    # 创建测试JSON数据
    local json_test_result
    json_test_result=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
JSON.SET user:1 . '{"name":"张三","age":30,"email":"zhangsan@example.com","address":{"city":"北京","street":"朝阳路"}}'
JSON.GET user:1
EOF
)
    
    if [ $? -eq 0 ] && echo "$json_test_result" | grep -q "张三"; then
        log_success "RedisJSON基本功能测试通过"
        
        # 测试JSON路径查询
        local path_test_result
        path_test_result=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
JSON.GET user:1 .name
JSON.GET user:1 .address.city
EOF
)
        
        if [ $? -eq 0 ] && echo "$path_test_result" | grep -q "北京"; then
            log_success "RedisJSON路径查询测试通过"
        else
            log_warn "RedisJSON路径查询测试失败"
        fi
        
        # 清理测试数据
        redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" del user:1 > /dev/null 2>&1
        return 0
    else
        log_error "RedisJSON功能测试失败"
        log_info "可能原因：模块未正确加载、权限不足或命令语法问题"
        return 1
    fi
}

# 测试RediSearch功能
test_redisearch() {
    log_info "测试RediSearch功能..."
    
    # 检查RediSearch模块是否可用
    if ! redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
FT._LIST
EOF
    then
        log_warn "RediSearch模块可能未正确加载或权限不足"
        
        # 诊断信息：检查具体错误
        log_info "诊断信息：尝试直接执行FT.CREATE命令..."
        local diagnostic_result
        diagnostic_result=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>&1
FT.CREATE test_diagnostic ON HASH PREFIX 1 test: SCHEMA field TEXT
EOF
)
        log_info "诊断结果: $diagnostic_result"
        
        return 1
    fi
    
    # 创建搜索索引
    local search_test_result
    search_test_result=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
FT.CREATE product_idx ON HASH PREFIX 1 product: SCHEMA \
    name TEXT WEIGHT 5.0 \
    description TEXT \
    price NUMERIC \
    category TAG

HSET product:1 name "iPhone 15" description "最新款苹果手机" price 5999 category "手机"
HSET product:2 name "MacBook Pro" description "高性能笔记本电脑" price 12999 category "电脑"
HSET product:3 name "AirPods" description "无线蓝牙耳机" price 1299 category "配件"

FT.SEARCH product_idx "苹果"
EOF
)
    
    if [ $? -eq 0 ] && echo "$search_test_result" | grep -q "iPhone"; then
        log_success "RediSearch基本功能测试通过"
        
        # 测试复杂搜索
        local complex_search_result
        complex_search_result=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
FT.SEARCH product_idx "@category:{手机} @price:[1000 10000]"
EOF
)
        
        if [ $? -eq 0 ]; then
            log_success "RediSearch复杂查询测试通过"
        else
            log_warn "RediSearch复杂查询测试失败"
        fi
        
        # 清理测试数据
        redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
FT.DROP product_idx
DEL product:1 product:2 product:3
EOF
        return 0
    else
        log_error "RediSearch功能测试失败"
        log_info "可能原因：模块未正确加载、权限不足或索引创建失败"
        return 1
    fi
}

# 测试RedisGraph功能
test_redisgraph() {
    log_info "测试RedisGraph功能..."
    
    # 检查RedisGraph模块是否存在（Redis Stack 7.2+版本中graph模块已移除）
    if ! redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
GRAPH.LIST
EOF
    then
        log_info "RedisGraph模块在当前Redis Stack版本中已移除，跳过测试"
        log_info "注：RedisGraph在Redis Stack 7.2+版本中不再包含"
        return 2  # 返回2表示跳过测试
    fi
    
    # 创建图数据
    local graph_test_result
    graph_test_result=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
GRAPH.QUERY social "CREATE (:person {name: 'Alice', age: 30})-[:knows {since: 2020}]->(:person {name: 'Bob', age: 25})"
GRAPH.QUERY social "MATCH (p:person) RETURN p.name, p.age"
EOF
)
    
    if [ $? -eq 0 ] && echo "$graph_test_result" | grep -q "Alice"; then
        log_success "RedisGraph基本功能测试通过"
        
        # 测试图查询
        local graph_query_result
        graph_query_result=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
GRAPH.QUERY social "MATCH (a:person)-[r:knows]->(b:person) RETURN a.name, b.name, r.since"
EOF
)
        
        if [ $? -eq 0 ] && echo "$graph_query_result" | grep -q "Bob"; then
            log_success "RedisGraph关系查询测试通过"
        else
            log_warn "RedisGraph关系查询测试失败"
        fi
        
        # 清理测试数据
        redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
GRAPH.DELETE social
EOF
        return 0
    else
        log_warn "RedisGraph功能测试失败（可能模块未完全加载）"
        return 1
    fi
}

# 测试RedisTimeSeries功能
test_redistimeseries() {
    log_info "测试RedisTimeSeries功能..."
    
    # 检查RedisTimeSeries模块是否可用
    if ! redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
TS.INFO test_timeseries
EOF
    then
        log_warn "RedisTimeSeries模块可能未正确加载或权限不足"
        
        # 诊断信息：检查具体错误
        log_info "诊断信息：尝试直接执行TS.CREATE命令..."
        local diagnostic_result
        diagnostic_result=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>&1
TS.CREATE test_diagnostic LABELS test "diagnostic"
EOF
)
        log_info "诊断结果: $diagnostic_result"
        
        return 1
    fi
    
    # 创建时间序列数据
    local current_timestamp
    current_timestamp=$(date +%s000)  # 转换为毫秒
    
    local timeseries_test_result
    timeseries_test_result=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
TS.CREATE temperature LABELS sensor_id 1 location "北京"
TS.ADD temperature $current_timestamp 25.5
TS.RANGE temperature - +
EOF
)
    
    if [ $? -eq 0 ] && echo "$timeseries_test_result" | grep -q "25.5"; then
        log_success "RedisTimeSeries基本功能测试通过"
        
        # 测试聚合查询
        local aggregate_test_result
        aggregate_test_result=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
TS.CREATE humidity LABELS sensor_id 2 location "上海"
TS.ADD humidity $current_timestamp 65.2
TS.ADD humidity $(($current_timestamp + 60000)) 68.1

TS.RANGE humidity - + AGGREGATION avg 60000
EOF
)
        
        if [ $? -eq 0 ]; then
            log_success "RedisTimeSeries聚合查询测试通过"
        else
            log_warn "RedisTimeSeries聚合查询测试失败"
        fi
        
        # 清理测试数据
        redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
DEL temperature humidity
EOF
        return 0
    else
        log_warn "RedisTimeSeries功能测试失败（可能模块未完全加载或权限不足）"
        return 1
    fi
}

# 测试RedisBloom功能
test_redisbloom() {
    log_info "测试RedisBloom功能..."
    
    # 检查RedisBloom模块是否可用
    if ! redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
BF.ADD test_bloom "test"
EOF
    then
        log_warn "RedisBloom模块可能未正确加载或权限不足"
        
        # 诊断信息：检查具体错误
        log_info "诊断信息：尝试直接执行BF.ADD命令..."
        local diagnostic_result
        diagnostic_result=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>&1
BF.ADD test_diagnostic "diagnostic"
EOF
)
        log_info "诊断结果: $diagnostic_result"
        
        return 1
    fi
    
    # 测试布隆过滤器
    local bloom_test_result
    bloom_test_result=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
BF.RESERVE user_filter 0.01 1000
BF.ADD user_filter "user123"
BF.ADD user_filter "user456"
BF.EXISTS user_filter "user123"
BF.EXISTS user_filter "user999"
EOF
)
    
    if [ $? -eq 0 ] && echo "$bloom_test_result" | grep -q "1" && echo "$bloom_test_result" | grep -q "0"; then
        log_success "RedisBloom布隆过滤器测试通过"
        
        # 测试计数器布隆过滤器
        local cuckoo_test_result
        cuckoo_test_result=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
CF.RESERVE item_counter 1000
CF.ADD item_counter "item1"
CF.ADD item_counter "item1"
CF.COUNT item_counter "item1"
EOF
)
        
        if [ $? -eq 0 ] && echo "$cuckoo_test_result" | grep -q "2"; then
            log_success "RedisBloom计数器布隆过滤器测试通过"
        else
            log_warn "RedisBloom计数器布隆过滤器测试失败"
        fi
        
        # 清理测试数据
        redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --eval /dev/stdin <<-'EOF' 2>/dev/null
DEL user_filter item_counter
EOF
        return 0
    else
        log_warn "RedisBloom功能测试失败（可能模块未完全加载或权限不足）"
        return 1
    fi
}

# 主测试函数
main() {
    # 初始化日志系统
    init_log_system
    
    echo "==============================================="
    echo "Redis Stack 功能测试脚本 v1.1"
    echo "测试时间: $(date)"
    echo "日志文件: $LOG_FILE"
    echo "Redis服务: $REDIS_HOST:$REDIS_PORT"
    echo "==============================================="
    echo ""
    
    # 检查连接
    if ! check_redis_connection; then
        log_error "测试终止: Redis连接失败"
        log_to_file "ERROR" "测试终止: Redis连接失败"
        exit 1
    fi
    
    # 检查模块
    if ! check_redis_modules; then
        log_warn "部分模块可能未加载，继续测试..."
        log_to_file "WARN" "部分Redis Stack模块可能未加载，继续测试"
    fi
    
    echo ""
    echo "开始功能测试..."
    echo "==============================================="
    log_to_file "INFO" "开始Redis Stack功能测试"
    
    local test_results=()
    local file_test_results=()
    
    # 执行各项测试
    if test_redisjson; then
        test_results+=("RedisJSON: ✅ 通过")
        file_test_results+=("RedisJSON: 通过")
    else
        test_results+=("RedisJSON: ❌ 失败")
        file_test_results+=("RedisJSON: 失败")
    fi
    
    if test_redisearch; then
        test_results+=("RediSearch: ✅ 通过")
        file_test_results+=("RediSearch: 通过")
    else
        test_results+=("RediSearch: ❌ 失败")
        file_test_results+=("RediSearch: 失败")
    fi
    
    if test_redisgraph; then
        test_results+=("RedisGraph: ✅ 通过")
        file_test_results+=("RedisGraph: 通过")
    else
        test_results+=("RedisGraph: ❌ 失败")
        file_test_results+=("RedisGraph: 失败")
    fi
    
    if test_redistimeseries; then
        test_results+=("RedisTimeSeries: ✅ 通过")
        file_test_results+=("RedisTimeSeries: 通过")
    else
        test_results+=("RedisTimeSeries: ❌ 失败")
        file_test_results+=("RedisTimeSeries: 失败")
    fi
    
    if test_redisbloom; then
        test_results+=("RedisBloom: ✅ 通过")
        file_test_results+=("RedisBloom: 通过")
    else
        test_results+=("RedisBloom: ❌ 失败")
        file_test_results+=("RedisBloom: 失败")
    fi
    
    echo ""
    echo "==============================================="
    echo "测试结果汇总:"
    echo "==============================================="
    
    # 记录测试结果到控制台和文件
    for result in "${test_results[@]}"; do
        echo "$result"
    done
    
    # 记录详细测试结果到日志文件
    echo "" >> "$LOG_FILE"
    echo "===============================================" >> "$LOG_FILE"
    echo "测试结果汇总:" >> "$LOG_FILE"
    echo "===============================================" >> "$LOG_FILE"
    for result in "${file_test_results[@]}"; do
        echo "$result" >> "$LOG_FILE"
    done
    
    # 计算通过率
    local total_tests=${#test_results[@]}
    local passed_tests=0
    for result in "${file_test_results[@]}"; do
        if [[ "$result" == *"通过"* ]]; then
            ((passed_tests++))
        fi
    done
    
    local success_rate=$((passed_tests * 100 / total_tests))
    
    echo ""
    echo "测试完成!"
    echo "通过率: $success_rate% ($passed_tests/$total_tests)"
    echo "详细日志请查看: $LOG_FILE"
    echo "==============================================="
    
    # 记录完成信息到日志文件
    echo "" >> "$LOG_FILE"
    echo "===============================================" >> "$LOG_FILE"
    echo "测试完成时间: $(date)" >> "$LOG_FILE"
    echo "通过率: $success_rate% ($passed_tests/$total_tests)" >> "$LOG_FILE"
    echo "===============================================" >> "$LOG_FILE"
    
    log_success "Redis Stack功能测试完成，通过率: $success_rate%"
}

# 脚本执行入口
if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
    echo "Redis Stack功能测试脚本使用方法:"
    echo "  ./redis-stack-test.sh           # 执行完整测试"
    echo "  ./redis-stack-test.sh --help   # 显示帮助信息"
    echo ""
    echo "配置参数 (可在脚本开头修改):"
    echo "  REDIS_HOST: $REDIS_HOST"
    echo "  REDIS_PORT: $REDIS_PORT"
    echo "  REDIS_PASSWORD: [已配置]"
    echo ""
    echo "日志功能:"
    echo "  • 脚本会在同级的logs目录中生成详细日志"
    echo "  • 日志文件名格式: redis-stack-test-YYYYMMDD-HHMMSS.log"
    echo "  • 日志包含所有测试步骤、结果和错误信息"
    echo "  • 控制台输出和文件日志同步记录"
    exit 0
fi

# 执行主函数
main